package thread;

public class DeadLockThread extends Thread{

	private byte[] lock = new byte[0];
	
	@Override
	public void run() {
		synchronized(lock){
			causeDeadlock(lock);
			System.out.println(Thread.currentThread().getName() + " finished.");
		}
		//System.out.println(Thread.currentThread().getName() + " finished.");
	}
	
	private void causeDeadlock(final Object lock) {
		Thread t2 = new Thread(new Runnable(){
			public void run() {
				synchronized(lock) {
					System.out.println("You can nerver see this.");
				}
			}
		});
		t2.start();
		try {
			//t1.join(5000);
			t2.join(); // t2加入中断t1，但t1未释放lock，t2拿不到lock，一直等待，悲剧了
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) throws Exception{
		DeadLockThread t1 = new DeadLockThread();
		t1.start();
	}
}

class DeadLock2 {
	
	private static class Function {
		private Function(){}
		synchronized void method() {
			System.out.println(Thread.currentThread().getName()+" ");
		}
	}
	private static Function f1 = new Function();
	private static Function f2 = new Function();
	
	private static Thread instance1 = new Thread() {
		@Override
		public void run() {
			synchronized(f1){
				System.out.println("entered instance1 sync");
				yield();
				f2.method();
			}
		}
	};
	
	private static Thread instance2 = new Thread() {
		@Override
		public void run() {
			synchronized(f2){
				System.out.println("entered instance2 sync");
				yield();
				f1.method();
			}
		}
	};
	
	public static void main(String[] args) {
		instance1.start();
		instance2.start();
	}
}

class DeadLockThread3 extends Thread {
	
	static class Function{
		private int count;
		private Function fellow;
		void setFellow(Function fellow) {
			this.fellow = fellow;
		}
		
		synchronized void add() {
			System.out.println(Thread.currentThread().getName()+": add");
			count++ ;
			Thread.yield();
			fellow.minus();
		}
		
		synchronized void minus() {
			System.out.println(Thread.currentThread().getName()+": minus");
			count-- ;
		}
	}
	
	private Function function;
	
	public DeadLockThread3(Function function) {
		this.function = function;
	}
	
	@Override
	public void run() {
		for (int i = 0; i < 10000; i++) {
			function.add();
		}
	}
	
	public static void main(String[] args) {
		DeadLockThread3.Function f1 = new DeadLockThread3.Function();
		DeadLockThread3.Function f2 = new DeadLockThread3.Function();
		f1.setFellow(f2);
		f2.setFellow(f1);
		DeadLockThread3 t1 = new DeadLockThread3(f1);
		DeadLockThread3 t2 = new DeadLockThread3(f2);
		t1.start();
		t2.start();
	}
}

class DeadLock4 {

	public DeadLock4() {
		t1.start();
		t2.start();
	}

	Thread t1 = new Thread() {
		public void run() {
			synchronized (this) {
				try {
					sleep(1);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (t2) {
					System.out.println("Oops...");
				}
			}
		};
	};

	Thread t2 = new Thread() {
		public void run() {
			synchronized (this) {
				try {
					sleep(1);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				synchronized (t1) {
					System.out.println("Oops...");
				}
			}
		}
	};

	public static void main(String[] args) {
		new DeadLock4();
	}
}

class DeadLock5 {
	public static void main(String[] args) {
		synchronized (DeadLock5.class) {
			Thread jt = new Thread() {
				public void run() {
					System.out.println("jt started!");
					synchronized (DeadLock5.class) {
						System.out.println("Oops...");
					}
				};
			};
			jt.start();
			try {
				jt.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("Oops...");
	}
}